package common.dao.config;

import common.dao.elastic.ElasticAdministratorHttpHelper;
import common.dao.elastic.ElasticAdministratorTransHelper;
import common.dao.elastic.ElasticClientHelper;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.client.transport.TransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import common.config.IndexTypeNames;
import common.dao.elastic.ElasticSearchDao;

/**
 * Created by Common on 7/17/16.
 */
public class ServerConfigurer {
    final Logger logger = LoggerFactory.getLogger(ServerConfigurer.class);

    final private String settingPath = "/elastic_admin/_settings.json";
    final private String aliasesPath = "/elastic_admin/_aliases.json";
    final private String tcpPath = "/elastic_admin/tcp_servers.json";
    final private String httpPath = "/elastic_admin/http_servers.json";
    final private String analysisPath = "/elasticsearch/analysis_v1.6.json";
    final private String mappingPath = "/elasticsearch/video_v1.6.json";
    //final private String riverPath = "/mongodb_rivers/";

    final private String indexName = IndexTypeNames.MediaDB.getIndexName();//"media";
    final private String aliasName = "meizi";
    final private String[] typeNames = IndexTypeNames.MediaDB.getTypeNames();//{"program" , "sequence" , "scene", "shot"};

    //final private ObjectMapper mapper;
    //final private TransportClient esClient;
    //private TransportClient esClient;
    //final private BulkProcessor bulkProcessor;
    //private BulkProcessor bulkProcessor;

    private ElasticAdministratorTransHelper adminClient;


    public ServerConfigurer(){
        this.adminClient = new ElasticAdministratorTransHelper(tcpPath);
    }

    @Override
    protected void finalize(){
        try {
            super.finalize();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        adminClient.esClient.close();
    }


    public  void initServer(){

        initElasticSearch_v2();
        logger.info("[init config] config elasticsearch successfully!");

        initGremlinGraph();
        logger.info("[init config] config gremlingraph  successfully!");


    }

    public void initElasticSearch_v2() {
        logger.info("[initElasticSearch_v2]");

        boolean exist = false;
        if(this.adminClient.is_index_exist( indexName )){
            exist = true;
            logger.info("[initElasticSearch_v2] index = {} alredy exit!", indexName);
        }
        else{
            //setUpElasticSearch();
            logger.info("[initElasticSearch_v2] index = {} not exit! will create!", indexName);
        }

        if(!exist){
            setUpElasticSearch();
        }

    }

    public void setUpElasticSearch(){
        logger.info("[setUpElasticSearch]");

        //ElasticAdministratorTransHelper adminClient = new ElasticAdministratorTransHelper(tcpPath);
        // 1) connect
        //this.esClient = adminClient.createTransportClient(tcpPath);
        TransportClient esClient = adminClient.esClient;
        if(esClient != null) logger.info ("[1] Connected with Elasticsearch");
        if(esClient == null) logger.error("[1] can not establish Connnection with Elasticsearch");

        // 2) create index
        adminClient.createIndex(indexName);
        logger.info("[2] creating index...");
        int check_retry = 20;
        while (check_retry > 0 && this.adminClient.is_index_exist(indexName) == false){
            ElasticClientHelper.waitSeconds(3);
            logger.info("[index not ready!]");
            check_retry -= 1;
        }
        if(check_retry == 0){
            logger.error("create index not success!");
            return;
        }


        // 3) create aliases
        adminClient.aliasIndex(indexName, aliasName);
        logger.info("[3] create aliases");

        // 4) close index
        adminClient.closeIndex(indexName);
        logger.info("[4] closing... index");
        ElasticClientHelper.waitSeconds(10);
        //if(ElasticAdministratorHttpHelper.is_index_open(indexName) != false) {retry};

        // 5) set analysis
        //adminClient.setAnalysis(indexName, analysisPath);
        int max_retry = 20;
        boolean ret = false;
        do {
            ElasticClientHelper.waitSeconds(3);
            ret = ElasticAdministratorHttpHelper.settingAnalysis(indexName, httpPath, analysisPath);
            max_retry -= 1;
        }
        while (!ret && max_retry > 0);
        logger.info("[5] set analysis");


        // 6) open index
        adminClient.openIndex(indexName);
        logger.info("[6] opening... index");
        ElasticAdministratorHttpHelper.is_index_open(indexName);


        // 7) set mapping
        ElasticClientHelper.waitSeconds(3);
        ElasticAdministratorHttpHelper.settingVideoMapping(indexName, IndexTypeNames.MediaDB.getVideoTypeName(), httpPath, mappingPath);
        ElasticAdministratorHttpHelper.settingMapiings(indexName, typeNames, httpPath, mappingPath);
        logger.info("[7] set mapping");


        // 8) bulkProcessor
        BulkProcessor bulkProcessor = BulkProcessor.builder(esClient, new ElasticSearchDao.MyBulkProcessorListener()).build();

        // 9) close connection
        //adminClient.esClient.close();
        //this.esClient.close();

    }


    public void initElasticSearch_v1(){
        logger.info("[initElasticSearch_v1]");
        // 1) connect to elasticsearch
        // Using config file elastic_admin/tcp_servers.json
        //this.esClient = ElasticAdministratorHttpHelper.createTransportClient(tcpPath);
        TransportClient esClient = adminClient.esClient;

        if(esClient != null) logger.info("Connected with Elasticsearch");
        if(esClient == null) logger.warn("can not establish Connnection with Elasticsearch");

        // 2) create index
        // Using Elasticsearch Beyonder, Using config files in the elasticsearch folder under resources
        /*
        try {
            ElasticsearchBeyonder.start(esClient);
        } catch (Exception e) {
            logger.warn("can not create index and mappings", e);
        }
        */
        // delete index
        //boolean retdel = ElasticAdministratorHttpHelper.deleteIndex(indexName,httpPath);
        //logger.debug("delete index ret = {}\n\n", retdel);
        // create index
        ElasticClientHelper.waitSeconds(3);
        boolean retcrt = ElasticAdministratorHttpHelper.createIndex(indexName,httpPath, "/elastic_admin/_settings.json");
        logger.debug("create index ret = {}\n\n", retcrt);

        // 3) create aliases
        // Using config file elastic_admin/_aliases.json
        // http://elasticsearch-users.115913.n3.nabble.com/Working-with-aliases-using-Java-API-td3300648.html
        ElasticClientHelper.waitSeconds(3);
        ElasticAdministratorHttpHelper.setAliases(esClient, aliasesPath);

        //4) set analysis
        // close index
        ElasticClientHelper.waitSeconds(3);
        boolean retcls = ElasticAdministratorHttpHelper.closeIndex(indexName ,httpPath );
        logger.debug("close index ret = {}\n\n", retcls);
        // set analysis
        boolean retanl = false;
        do {
            ElasticClientHelper.waitSeconds(3);
            retanl = ElasticAdministratorHttpHelper.settingAnalysis(indexName, httpPath, "/elasticsearch/analysis_v1.6.json");
        }
        while (retanl == false);
        logger.debug("set index ret = {}\n\n", retanl);
        // open index
        ElasticClientHelper.waitSeconds(3);
        boolean retopn = ElasticAdministratorHttpHelper.openIndex(indexName ,httpPath );
        logger.debug("open index ret = {}\n\n", retopn);

        // 5) set mapping
        ElasticClientHelper.waitSeconds(3);
        boolean retvideo = ElasticAdministratorHttpHelper.settingVideoMapping(indexName, IndexTypeNames.MediaDB.getVideoTypeName(), httpPath, "/elasticsearch/video_v1.6.json");
        boolean retmap =   ElasticAdministratorHttpHelper.settingMapiings(indexName, typeNames, httpPath, "/elasticsearch/video_v1.6.json");
        logger.debug("setting mappins ret = {}\n\n", retmap);

        // 6) create Mongodb River
        // Using google-http-client library, Using config file elastic_admin/tcp_servers.json to get HTTP endpoint
        // ElasticAdministratorHttpHelper.putMongodbRiver(httpPath, riverPath);

        /**************************************************************/

    }


    public  void initGremlinGraph(){
        logger.info("[initGremlinGraph]");


    }


    /****************
     *
     * @param args
     */
    public static void main(String[] args){

        new ServerConfigurer().initElasticSearch_v2();

    }


}
